package org.gim.utils;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import org.springframework.stereotype.Component;

import java.io.File;
import java.text.DecimalFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.Random;
import java.util.regex.Pattern;

import static com.aliyun.oss.internal.OSSConstants.KB;

@Component
public class CommonUtils {

    private static final Random random = new Random();

    /**
     * 校验手机验证码是否合法
     */
    public static boolean checkMobile(String mobile) {

        if(ObjectUtil.isNotNull(mobile) && ObjectUtil.isNotEmpty(mobile)){
            return Pattern.matches("^1[3-9]\\d{9}$", mobile);
        }

        return false;
    }

    /**
     * 生成一个指定位数的随机数字字符串
     *
     * @param length 随机数字字符串的长度
     * @return 随机数字字符串
     */
    public String randomNumbers(int length) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append(random.nextInt(10)); // 生成0-9之间的随机数字
        }
        return sb.toString();
    }

    /**
     * 计算当前时间 距离Date 数据 天数
     * @param args
     */
    /**
     * 计算给定日期与当前时间的相差天数
     *
     * @param targetDate 目标日期（如果为 null，默认返回 0）
     * @return 相差天数（正数：目标日期在未来；负数：目标日期在过去）
     */
    public static Integer daysBetweenNow(Date targetDate) {

        if (targetDate == null) {
            return 0;
        }

        long days = DateUtil.betweenDay(targetDate,DateUtil.date(), true);

        // 安全转为 Integer（处理溢出）
        if (days > Integer.MAX_VALUE) {
            return Integer.MAX_VALUE;
        } else if (days < Integer.MIN_VALUE) {
            return Integer.MIN_VALUE;
        } else {
            return (int) days;
        }
    }

    /**
     * 根据时间戳 - 生成业务ID
     */
    public static String generateShortUniqueId() {
        long timestamp = System.currentTimeMillis(); // 毫秒级时间戳
        int random = (int)(Math.random() * 9000) + 1000; // 4位随机数
        return Long.toString(timestamp, 36) + Integer.toString(random, 36);
    }

    private static LocalDateTime convertToLocalDateTime(Date date) {
        if (date == null) return null;
        return Instant.ofEpochMilli(date.getTime())
                .atZone(ZoneId.systemDefault())
                .toLocalDateTime();
    }

    /**
     * 格式化时间差，显示 X分钟前、X小时前、X天前、X月前、X年前
     */
    public static String formatTimeAgo(Date updateTime) {
        if (updateTime == null) return "";

        LocalDateTime updateDateTime = convertToLocalDateTime(updateTime);
        LocalDateTime now = LocalDateTime.now();

        long years = ChronoUnit.YEARS.between(updateDateTime, now);
        if (years >= 1) {
            return years + "年前";
        }

        long months = ChronoUnit.MONTHS.between(updateDateTime, now);
        if (months >= 1) {
            return months + "个月前";
        }

        long days = ChronoUnit.DAYS.between(updateDateTime, now);
        if (days >= 1) {
            return days + "天前";
        }

        long hours = ChronoUnit.HOURS.between(updateDateTime, now);
        if (hours >= 1) {
            return hours + "小时前";
        }

        long minutes = ChronoUnit.MINUTES.between(updateDateTime, now);
        if (minutes >= 1) {
            return minutes + "分钟前";
        }

        return "刚刚";
    }

    public static void main(String[] args) throws InterruptedException {
        Date now = new Date();

        System.out.println(formatTimeAgo(new Date(now.getTime() - 45 * 60 * 1000))); // 45分钟前
        System.out.println(formatTimeAgo(new Date(now.getTime() - 3 * 60 * 60 * 1000))); // 3小时前
        System.out.println(formatTimeAgo(new Date(now.getTime() - 5L * 24 * 3600 * 1000))); // 5天前
        System.out.println(formatTimeAgo(Date.from(LocalDateTime.now().minusMonths(4)
                .atZone(ZoneId.systemDefault()).toInstant()))); // 4月前
        System.out.println(formatTimeAgo(Date.from(LocalDateTime.now().minusYears(2)
                .atZone(ZoneId.systemDefault()).toInstant()))); // 2年前
        System.out.println(formatTimeAgo(new Date())); // 刚刚
    }

    private static final long MB = KB * 1024;
    private static final long GB = MB * 1024;
    private static final DecimalFormat df = new DecimalFormat("#.##");

    /**
     * 根据文件大小自动转换为最合适的单位
     * @param file 要计算的文件
     * @return 带有单位的文件大小字符串
     */
    public static String getAutoFileSize(File file) {
        long sizeInBytes = file.length();
        return formatSize(sizeInBytes);
    }

    /**
     * 根据字节大小自动转换为最合适的单位
     * @param sizeInBytes 文件大小(字节)
     * @return 带有单位的文件大小字符串
     */
    public static String formatSize(long sizeInBytes) {
        if (sizeInBytes < KB) {
            return sizeInBytes + " B";
        } else if (sizeInBytes < MB) {
            return df.format((double) sizeInBytes / KB) + " KB";
        } else if (sizeInBytes < GB) {
            return df.format((double) sizeInBytes / MB) + " MB";
        } else {
            return df.format((double) sizeInBytes / GB) + " GB";
        }
    }

    /**
     * 转换为指定单位的大小
     * @param sizeInBytes 文件大小(字节)
     * @param unit 单位(B, KB, MB, GB)
     * @return 转换后的数值
     */
    public static double convertToSpecificUnit(long sizeInBytes, String unit) {
        switch (unit.toUpperCase()) {
            case "KB":
                return (double) sizeInBytes / KB;
            case "MB":
                return (double) sizeInBytes / MB;
            case "GB":
                return (double) sizeInBytes / GB;
            default: // 默认返回字节
                return sizeInBytes;
        }
    }

    /**
     * 转换为指定单位的大小字符串
     * @param sizeInBytes 文件大小(字节)
     * @param unit 单位(B, KB, MB, GB)
     * @return 带有单位的文件大小字符串
     */
    public static String convertToSpecificUnitString(long sizeInBytes, String unit) {
        return df.format(convertToSpecificUnit(sizeInBytes, unit)) + " " + unit;
    }

}
